package com.tan.chowder.login.config;

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import java.util.Arrays;

import static org.springframework.security.config.http.SessionCreationPolicy.STATELESS;


/**
 * 安全策略
 *
 * @author chenx
 */
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableMethodSecurity
public class SecurityConfig {

    /**
     * 白名单路径
     */
    private static final String[] WHITE_LIST_URL = {"/user/login"};
    /**
     * 过滤器：请求处理之前验证JWT
     */
    private final JwtAuthenticationFilter jwtAuthFilter;

    private final AuthenticationProvider authenticationProvider;


    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        System.out.println(" =======安全策略启动===== ");
        System.out.printf(" =======白名单%s===== %n", Arrays.toString(WHITE_LIST_URL));
        // 禁用CSRF保护 globally
        http.csrf(AbstractHttpConfigurer::disable)
                // 除白名单外，都需要身份验证
                .authorizeHttpRequests(req ->
                        req.requestMatchers(WHITE_LIST_URL)
                                .permitAll()
                                // 拒绝访问除以上URL以外的所有请求
                                .anyRequest()
                                // 要求身份验证
                                .authenticated())
                // 使用不存储会话的会话策略
                .sessionManagement(session -> session.sessionCreationPolicy(STATELESS))
                // 使用JWT认证提供者
                .authenticationProvider(authenticationProvider)
                // 在JWT认证过滤器之前添加用户名密码认证过滤器
                .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class)
                // 配置注销流程
                .logout(logout ->
                        // 设置注销URL
                        logout.logoutUrl("/user/logout")
                                // 在注销成功后清除安全上下文
                                .logoutSuccessHandler((request, response, authentication) -> SecurityContextHolder.clearContext()));

        //单用户登录，如果有一个登录了，同一个用户在其他地方不能登录
        //http.sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true);
        //单用户登录，如果有一个登录了，同一个用户在其他地方登录将前一个剔除下线
        //http.sessionManagement().maximumSessions(1).expiredUrl("/toLogin");

        // 返回配置好的HTTP安全策略
        return http.build();
    }

}
